#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>


#define SIZE 1024
#define MAX_ARGC 64
#define SEP " "

char* argv[MAX_ARGC];
char pwd[SIZE];
char env[SIZE];//for text
int lastcode = 0;

const char* HostName()
{
    char* hostname = getenv("HOSTNAME");
    if (hostname) return hostname;
    else return "None";
}

const char* UserName()
{
    
    char* hostname = getenv("USER");
    if (hostname) return hostname;
    else return "None";
}

const char* CurrentWorkDir()
{

    char* hostname = getenv("PWD");
    if (hostname) return hostname;
    else return "None";
}
 
int Interactive(char out[], int size)
{
    //输出提示符并获取用户输入的命令字符串
    fgets(out,size, stdin);
    out[strlen(out) - 1] = '\0';//清除最后的\n
    return strlen(out);
}


void Split(char in[])
{
    int i = 0;
    argv[i++] = strtok(in, SEP);
    while (argv[i++] = strtok(NULL, SEP));
    if (strcmp("ls", argv[0]) == 0)
    {
        argv[i - 1] = (char*)"--color";
        argv[i] = NULL;
    }
}

void Execut()
{

    pid_t id = fork();
    if (id == 0)
    {
        //让子进程执行
        execvp(argv[0], argv);
        exit(1);
    }
    int status = 0;
    pid_t rid = waitpid(id, &status, 0);//回收子进程的退出信息，防止子进程变成僵尸进程
    if (rid == id) lastcode = WEXITSTATUS(status);
}

char*  Home()
{
    return getenv("HOME");
}

int BuildinCmd()
{
    int ret = 0;
    if (strcmp("cd", argv[0]) == 0)
    {
        ret = 1; 
        char* target = argv[1];
        if (!target) target = Home();
        //更改当前工作路径
        chdir(target);
        char tmp[1024];
        getcwd(tmp, 1024);//获取绝对路径
        snprintf(pwd, SIZE, "PWD=%s", tmp);
        putenv(pwd);//导出环境变量，跟新调用这个函数的进程的环境变量
    } 
    else if (strcmp("export", argv[0]) == 0)
    {
        ret = 1;
        if (argv[1]) 
        {
            strcpy(env, argv[1]);
            putenv(env);
        }
    }
    else if (strcmp("echo", argv[0]) == 0)
    {
        ret = 1;
        if (argv[1])
        {
            if (argv[1][0] == '$')
            {
                if (argv[1][1] == '?')
                {
                    printf("%d\n", lastcode);
                    lastcode = 0;
                }
                else{
                    char* e = getenv(argv[1]+1);
                    if (e) printf("%s\n",e );
                }
            }
            else
            {
                printf("%s\n", argv[1]);
            }
        }
        else
        {
            printf("\n");
        }
    }
    return ret;
}
 
int main()
{
    while(1)
    {
         //1. 打印命令行提示符，获取用户输入的命令行字符串
         printf("[%s@%s %s]$ ", UserName(),HostName(), CurrentWorkDir());
         char commandline[SIZE];
         //交互
         int n = Interactive(commandline, SIZE);
         if (n == 0) continue;//处理空串情况
         //2. 对命令行字符串进行切割
         Split(commandline);
         //3. 检查是否是内建命令
         n = BuildinCmd();
         if (n) continue;
         //4. 执行这个命令
         Execut();
    }

    return 0;
}
